// 跟网络相关的代码


#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#include "main.h"
#include "socket.h"
#include "device.h"
extern int g_socketfd;

static int client_sockfd;

static int tcp_is_connected(int fd)
{
    struct tcp_info info;
    int len = sizeof(info);
 
    if (fd <= 0) return 0;
 
    getsockopt(fd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
    if (info.tcpi_state == TCP_ESTABLISHED)
        return 1;
    else 
        return 0;
}

void *conenct_cb(void *arg)
{
    // struct sockaddr_in 地址端口分开标识
    // struct sockaddr 地址端口在一起不好配置
    struct sockaddr_in server_addr;
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);// 绑定端口
    server_addr.sin_addr.s_addr = (in_addr_t)inet_addr(SERVER_IP);
    bzero(&(server_addr.sin_zero), 8);   // zero the rest of the struct

    uint8_t count = 5;
    int ret = 0;
    int syncnt = 1;
    while(count--)
    {
        // 调用connect连接 需要struct sockaddr ， 强制转换 struct sockaddr_in  --> struct sockaddr
        printf("连接服务器%s:%d\n",SERVER_IP,SERVER_PORT);
        led_on(1);
        //Tcp SYN报文重传的次数
        setsockopt(g_socketfd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(syncnt));
        ret = connect(g_socketfd,(struct sockaddr *)&server_addr,sizeof(server_addr));
        if(-1 == ret)
        {
            perror("message:");
            //线程退出取消点
            pthread_testcancel();
            //线程休眠 todo:确定合适的线程休眠时间
            sleep(1);  
            continue;
        }
        led_on(0);
        printf("TCP client socket connnected\r\n");
        while(tcp_is_connected(g_socketfd))
        {
            usleep(3000);
        }

        close(g_socketfd);
        if((g_socketfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        {
            perror("TCP client socket create socket error!\r\n");
            return NULL;
        }  

        //线程退出取消点
        pthread_testcancel();
        //线程休眠 todo:确定合适的线程休眠时间
        sleep(1);    
    }


}

int InitSocket(void)
{

    printf("InitSocket...\n");
    g_socketfd = socket(AF_INET,SOCK_STREAM,0);
    if(-1 == g_socketfd)
    {
        perror("创建socket fialed: ");
        return FAILURE;
    }

    // 启动线程向服务器发送连接
    pthread_t tid;
    int ret = pthread_create(&tid,NULL,conenct_cb,NULL);
    if(0 != ret)
    {
        return FAILURE;
    }

    return SUCCESS;
}